#pragma once
#include "sock.hpp"
#include <pthread.h>
#include <functional>
#include "protocol.hpp"
#include <unistd.h>

using func_t = std::function<Response(Request)>;

class TCPServer;

class ThreadDate
{
public:
    ThreadDate(int sockId, TCPServer *this_)
        : _sockId(sockId), _this(this_)
    {
    }

    ~ThreadDate() {}

public:
    TCPServer *_this; // 任务函数
    int _sockId;
};

class TCPServer
{
public:
    TCPServer(uint16_t port, std::string ip = "0.0.0.0")
        : _port(port), _ip(ip)
    {
    }

    int Init()
    {
        int listen_sock = _sock.Socket();
        if (listen_sock < 0)
        {
            std::cout << "socket error" << std::endl;
            exit(1);
        }
        std::cout << "socket success" << std::endl;

        if (_sock.Bind(listen_sock, _port, _ip) < 0)
        {
            std::cout << "bind error" << std::endl;
            exit(1);
        }
        std::cout << "bind success" << std::endl;

        if (_sock.Listen(listen_sock) < 0)
        {
            std::cout << "listen error" << std::endl;
            exit(1);
        }
        std::cout << "listen success" << std::endl;
        std::cout << "TCPServer Init Success" << std::endl;
        return listen_sock;
    }

    void Start(int listen_sock)
    {
        std::cout << "TCPServer Running" << std::endl;
        while (true)
        {
            int sockId = _sock.Accept(listen_sock);
            if (sockId < 0)
            {
                std::cout << "accept error" << std::endl;
                continue;
            }
            std::cout << "accept success sock:" << sockId << std::endl;

            // 创建线程执行任务
            pthread_t tid;
            ThreadDate *td = new ThreadDate(sockId, this);
            pthread_create(&tid, nullptr, Service, td);
        }
    }

    void BindService(func_t func)
    {
        _func = func;
    }

    ~TCPServer()
    {
    }

public:
    static void *Service(void *args)
    {
        pthread_detach(pthread_self()); // 剥离线程，避免僵尸
        ThreadDate *td = (ThreadDate *)args;

        while (true)
        {
            // 获取数据
            std::string message;
            if (!Recv(td->_sockId, &message))
            {
                std::cout << "Recv error" << std::endl;
                exit(-1);
            }

            // 反序列化
            Request request;
            request.unserialize(message);

            Response response = td->_this->_func(request); // 计算

            std::string result = response.serialize(); // 序列化计算结果

            Send(td->_sockId, result); // 发送结果
        }

        close(td->_sockId);
        delete td;

        return nullptr;
    }

private:
    uint16_t _port;
    std::string _ip;
    Sock _sock;
    func_t _func;
};
